<!DOCTYPE html>

<html>
<head>
  <title>manager.coffee</title>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <link rel="stylesheet" media="all" href="public/stylesheets/normalize.css" />
  <link rel="stylesheet" media="all" href="docco.css" />
</head>
<body>
  <div class="container">
    <div class="page">

      <div class="header">
        
          <h1>manager.coffee</h1>
        

        
          <div class="toc">
            <h3>Table of Contents</h3>
            <ol>
              
                
                <li>
                  <a class="source" href="database.html">
                    database.coffee
                  </a>
                </li>
              
                
                <li>
                  <a class="source" href="manager.html">
                    manager.coffee
                  </a>
                </li>
              
                
                <li>
                  <a class="source" href="routes.html">
                    routes.coffee
                  </a>
                </li>
              
                
                <li>
                  <a class="source" href="security.html">
                    security.coffee
                  </a>
                </li>
              
                
                <li>
                  <a class="source" href="sockets.html">
                    sockets.coffee
                  </a>
                </li>
              
                
                <li>
                  <a class="source" href="sync.html">
                    sync.coffee
                  </a>
                </li>
              
            </ol>
          </div>
        
      </div>

      
        
        <h2 id="server-manager">SERVER MANAGER</h2>

        
      
        
        <p>Handles all automated server procedures like log cleaning, Audit Data
refresh, CMDB updates etc. The manager is started automatically with the app.</p>

        
          <div class='highlight'><pre><span class="class"><span class="keyword">class</span> <span class="title">Manager</span></span></pre></div>
        
      
        
        <p>Require Expresser.</p>

        
          <div class='highlight'><pre>    expresser = <span class="built_in">require</span> <span class="string">"expresser"</span>
    settings = expresser.settings</pre></div>
        
      
        
        <p>Required modules.</p>

        
          <div class='highlight'><pre>    database = <span class="built_in">require</span> <span class="string">"./database.coffee"</span>
    fs = <span class="built_in">require</span> <span class="string">"fs"</span>
    sockets = <span class="built_in">require</span> <span class="string">"./sockets.coffee"</span>
    sync = <span class="built_in">require</span> <span class="string">"./sync.coffee"</span></pre></div>
        
      
        
        <h2 id="timers-and-properties">TIMERS AND PROPERTIES</h2>

        
      
        
        
        
          <div class='highlight'><pre>    <span class="attribute">connectionErrorCount</span>: <span class="number">0</span>         <span class="comment"># How many consecutive connection errors the app manager's got.</span>
    <span class="attribute">timerDatabaseClean</span>: <span class="literal">null</span>        <span class="comment"># Holds the [Database](database.html) cleaner timer.</span>
    <span class="attribute">timersEntityRefresh</span>: <span class="literal">null</span>       <span class="comment"># Holds all [Entity](entities.html) refresh timers.</span>
    <span class="attribute">timersAuditDataRefresh</span>: <span class="literal">null</span>    <span class="comment"># Holds all [AuditData](auditData.html) refresh timers.</span></pre></div>
        
      
        
        <p>Holds the &quot;restart all&quot; timer. This is used in case the app identifies
multiple connection errors in a short period of time, meaning that
internet connection is broken or unreliable. In this case, all other
timers will be stopped and the restart timer will schedule a new restart
after a few seconds - value is defined at the <a href="settings.html">Settings</a>.</p>

        
          <div class='highlight'><pre>    <span class="attribute">timerRestartAll</span>: <span class="literal">null</span></pre></div>
        
      
        
        <h2 id="init">INIT</h2>

        
      
        
        <p>Init the app manager by starting all the necessary timers.</p>

        
          <div class='highlight'><pre>    <span class="attribute">init</span>:<span class="function"> =&gt;</span>
        <span class="keyword">if</span> <span class="keyword">not</span> expresser.database.db?
            setTimeout <span class="property">@init</span>, <span class="number">100</span>
            <span class="keyword">return</span>

        <span class="property">@initDatabaseTimer</span>()
        <span class="property">@initEntityTimers</span>()
        <span class="property">@initAuditDataTimers</span>()</pre></div>
        
      
        
        <h2 id="error-management">ERROR MANAGEMENT</h2>

        
      
        
        <p>Increase the connection error counter. and pass an optional error message do the manager.</p>

        
          <div class='highlight'><pre>    <span class="attribute">connectionError</span>:<span class="function"> =&gt;</span>
        <span class="property">@connectionErrorCount</span>++</pre></div>
        
      
        
        <h2 id="database-maintenance">DATABASE MAINTENANCE</h2>

        
      
        
        <p>Init the <a href="database.html">Database</a> cleaner timer.
Run the <code>cleanLogs</code> procedure every X seconds. The log &quot;expiry hours&quot; is defined on the
<a href="settings.html">Server Settings</a>. By default, logs will be stored for a minimum
of 2 hours and maximum of 3 hours.</p>

        
          <div class='highlight'><pre>    <span class="attribute">initDatabaseTimer</span>:<span class="function"> =&gt;</span>
        <span class="property">@stopDatabaseTimer</span>()
        <span class="property">@timerDatabaseClean</span> = setInterval database.cleanLogs, settings.database.logExpires * <span class="number">1800000</span></pre></div>
        
      
        
        <p>Stop the running database cleaner timer.</p>

        
          <div class='highlight'><pre>    <span class="attribute">stopDatabaseTimer</span>:<span class="function"> =&gt;</span>
        <span class="keyword">if</span> <span class="property">@timerDatabaseClean</span>?
            clearInterval <span class="property">@timerDatabaseClean</span>
        <span class="property">@timerDatabaseClean</span> = <span class="literal">null</span></pre></div>
        
      
        
        <h2 id="entity-manager">ENTITY MANAGER</h2>

        
      
        
        <p>Init the <a href="entityDefinition.html">Entity</a> refresh timers, by creating one interval
timer for each entity definition and transmitting the refreshed data to users via sockets.</p>

        
          <div class='highlight'><pre>    <span class="attribute">initEntityTimers</span>:<span class="function"> =&gt;</span>
        <span class="keyword">if</span> settings.general.debug
            expresser.logger.info <span class="string">"Manager.initEntityTimers"</span>

        <span class="property">@stopEntityTimers</span>()
        database.getEntityDefinition <span class="literal">null</span>, <span class="property">@startEntityTimers</span></pre></div>
        
      
        
        <p>Stop all running <a href="entityDefinition.html">Entity</a> refresh timers and
clear the <code>timersEntityRefresh</code> array.</p>

        
          <div class='highlight'><pre>    <span class="attribute">stopEntityTimers</span>:<span class="function"> =&gt;</span>
        <span class="keyword">if</span> <span class="property">@timersEntityRefresh</span>?
            clearInterval timer <span class="keyword">for</span> timer <span class="keyword">in</span> <span class="property">@timersEntityRefresh</span>
        <span class="property">@timersEntityRefresh</span> = []</pre></div>
        
      
        
        <p>Start the <a href="entityDefinition.html">Entity</a> timers based on the returned items
and error (if any) in result of the <code>getAuditData</code> database call.</p>

        
          <div class='highlight'><pre>    <span class="attribute">startEntityTimers</span>: <span class="function"><span class="params">(err, result)</span> =&gt;</span>
        <span class="keyword">if</span> err?
            sockets.sendServerError <span class="string">"Manager: could not load Entity Definition items."</span>, err
        <span class="keyword">else</span>
            <span class="property">@setEntityTimer</span> entityDef <span class="keyword">for</span> entityDef <span class="keyword">in</span> result
            <span class="keyword">if</span> settings.general.debug
                expresser.logger.info <span class="string">"Manager.startEntityTimers"</span>, <span class="string">"Started timers for <span class="subst">#{result.length}</span> entities."</span></pre></div>
        
      
        
        <p>Add an <a href="entityDefinition.html">Entity</a> refresh timer to the <code>timersEntityRefresh</code> array.</p>

        
          <div class='highlight'><pre>    <span class="attribute">setEntityTimer</span>: <span class="function"><span class="params">(entityDef)</span> =&gt;</span>
        <span class="function"><span class="title">callback</span> = =&gt;</span> <span class="property">@refreshEntity</span> entityDef
        interval = entityDef.refreshInterval</pre></div>
        
      
        
        <p>Make sure interval is at least 2 seconds.</p>

        
          <div class='highlight'><pre>        <span class="keyword">if</span> <span class="keyword">not</span> interval? <span class="keyword">or</span> interval &lt; settings.web.minimumRefreshInterval
            interval = settings.web.minimumRefreshInterval
            expresser.logger.warn <span class="string">"Entity Definition data refresh interval is too low: ID <span class="subst">#{entityDef.friendlyId}</span>, interval <span class="subst">#{entityDef.refreshInterval}</span> seconds."</span></pre></div>
        
      
        
        <p>Set the timer. Interval is in seconds, so we must multiply by 1000.</p>

        
          <div class='highlight'><pre>        timer = setInterval callback, interval * <span class="number">1000</span></pre></div>
        
      
        
        <p>Call the refresh immediatelly so clients will get updated data straight away.</p>

        
          <div class='highlight'><pre>        callback()

        <span class="property">@timersEntityRefresh</span>.push timer

        <span class="keyword">if</span> settings.general.debug
            expresser.logger.info <span class="string">"Manager.setEntityTimer"</span>, entityDef.friendlyId, interval + <span class="string">"s"</span></pre></div>
        
      
        
        <p>Refresh the specified <a href="entityDefinition.html">Entity</a> data. This will run ONLY
if there are connected clients, to avoid bandwidth and processing waste.</p>

        
          <div class='highlight'><pre>    <span class="attribute">refreshEntity</span>: <span class="function"><span class="params">(entityDef)</span> =&gt;</span>
        <span class="keyword">if</span> expresser.sockets.getConnectionCount() &lt; <span class="number">1</span>
            <span class="keyword">return</span></pre></div>
        
      
        
        <p>Only proceed if the entity sourceUrl is set.</p>

        
          <div class='highlight'><pre>        <span class="keyword">if</span> entityDef.sourceUrl? <span class="keyword">and</span> entityDef.sourceUrl <span class="keyword">isnt</span> <span class="string">""</span>
            sync.download entityDef.sourceUrl, settings.path.downloadsDir + <span class="string">"entityobjects."</span> + entityDef.friendlyId + <span class="string">".json"</span>, <span class="function"><span class="params">(err, localFile)</span> =&gt;</span>
                <span class="property">@transmitDataToClients</span> err, localFile, entityDef, sockets.sendEntityRefresh, database.setEntityDefinition
        <span class="keyword">else</span> <span class="keyword">if</span> settings.general.debug
            expresser.logger.warn <span class="string">"Manager.refreshEntity"</span>, entityDef.friendlyId, <span class="string">"No sourceUrl set. Abort."</span></pre></div>
        
      
        
        <h2 id="audit-data-manager">AUDIT DATA MANAGER</h2>

        
      
        
        <p>Init the <a href="auditadta.html">AuditData</a> refresh timers, by creating one interval
timer for each audit data and transmitting the refreshed data to users via sockets.</p>

        
          <div class='highlight'><pre>    <span class="attribute">initAuditDataTimers</span>:<span class="function"> =&gt;</span>
        <span class="keyword">if</span> settings.general.debug
            expresser.logger.info <span class="string">"Manager.initAuditDataTimers"</span>

        <span class="property">@stopAuditDataTimers</span>()
        database.getAuditData <span class="literal">null</span>, <span class="property">@startAuditDataTimers</span></pre></div>
        
      
        
        <p>Stop all running <a href="auditData.html">AuditData</a> refresh timers and
clear the <code>timersAuditDataRefresh</code> array.</p>

        
          <div class='highlight'><pre>    <span class="attribute">stopAuditDataTimers</span>:<span class="function"> =&gt;</span>
        <span class="keyword">if</span> <span class="property">@timersAuditDataRefresh</span>?
            clearInterval timer <span class="keyword">for</span> timer <span class="keyword">in</span> <span class="property">@timersAuditDataRefresh</span>
        <span class="property">@timersAuditDataRefresh</span> = []</pre></div>
        
      
        
        <p>Start the <a href="auditData.html">AuditData</a> timers based on the returned items
and error (if any) in result of the <code>getAuditData</code> database call.</p>

        
          <div class='highlight'><pre>    <span class="attribute">startAuditDataTimers</span>: <span class="function"><span class="params">(err, result)</span> =&gt;</span>
        <span class="keyword">if</span> err?
            sockets.sendServerError <span class="string">"Manager: could not load Audit Data items."</span>, err
        <span class="keyword">else</span>
            <span class="property">@setAuditDataTimer</span> auditData <span class="keyword">for</span> auditData <span class="keyword">in</span> result
            <span class="keyword">if</span> settings.general.debug
                expresser.logger.info <span class="string">"Manager.startAuditDataTimers"</span>, <span class="string">"Started timers for <span class="subst">#{result.length}</span> audit data."</span></pre></div>
        
      
        
        <p>Add an <a href="auditadata.html">AuditData</a> refresh timer to the <code>timersAuditDataRefresh</code> array.</p>

        
          <div class='highlight'><pre>    <span class="attribute">setAuditDataTimer</span>: <span class="function"><span class="params">(auditData)</span> =&gt;</span>
        <span class="function"><span class="title">callback</span> = =&gt;</span> <span class="property">@refreshAuditData</span> auditData
        interval = auditData.refreshInterval</pre></div>
        
      
        
        <p>Make sure interval is at least 2 seconds.</p>

        
          <div class='highlight'><pre>        <span class="keyword">if</span> <span class="keyword">not</span> interval? <span class="keyword">or</span> interval &lt; settings.web.minimumRefreshInterval
            interval = settings.web.minimumRefreshInterval
            expresser.logger.warn <span class="string">"Audit Data refresh interval is too low: ID <span class="subst">#{auditData.friendlyId}</span>, interval <span class="subst">#{auditData.refreshInterval}</span> seconds."</span></pre></div>
        
      
        
        <p>Set the timer. Interval is in seconds, so we must multiply by 1000.</p>

        
          <div class='highlight'><pre>        timer = setInterval callback, interval * <span class="number">1000</span></pre></div>
        
      
        
        <p>Call the refresh immediatelly so clients will get updated data straight away.</p>

        
          <div class='highlight'><pre>        callback()

        <span class="property">@timersAuditDataRefresh</span>.push timer

        <span class="keyword">if</span> settings.general.debug
            expresser.logger.info <span class="string">"Manager.setAuditDataTimer"</span>, auditData.friendlyId, interval + <span class="string">"ms"</span></pre></div>
        
      
        
        <p>Refresh the specified <a href="auditData.html">AuditData</a> records. This will run ONLY
if there are connected clients, to avoid bandwidth and processing waste.</p>

        
          <div class='highlight'><pre>    <span class="attribute">refreshAuditData</span>: <span class="function"><span class="params">(auditData)</span> =&gt;</span>
        <span class="keyword">if</span> expresser.sockets.getConnectionCount() &lt; <span class="number">1</span>
            <span class="keyword">return</span></pre></div>
        
      
        
        <p>Only proceed if the audit data sourceUrl is properly set.</p>

        
          <div class='highlight'><pre>        <span class="keyword">if</span> auditData.sourceUrl? <span class="keyword">and</span> auditData.sourceUrl <span class="keyword">isnt</span> <span class="string">""</span>
            sync.download auditData.sourceUrl, settings.path.downloadsDir + <span class="string">"auditdata."</span> + auditData.friendlyId + <span class="string">".json"</span>, <span class="function"><span class="params">(err, localFile)</span> =&gt;</span>
                <span class="property">@transmitDataToClients</span> err, localFile, auditData, sockets.sendAuditDataRefresh, database.setAuditData
        <span class="keyword">else</span> <span class="keyword">if</span> settings.general.debug
            expresser.logger.warn <span class="string">"Manager.refreshAuditData"</span>, auditData.friendlyId, <span class="string">"No sourceUrl set. Abort."</span></pre></div>
        
      
        
        <h2 id="helper-methods">HELPER METHODS</h2>

        
      
        
        <p>Transmit refreshed <code>data</code> to the connected clients/browsers via Socket.IO.
This can be for example the <code>data</code> attribute of an <a href="auditData..html">AuditData</a> or
the collection of <a href="entityObject.html">Entity Objects</a> from an <a href="entityDefinition.html">Entity Definition</a>.
The <code>socketsCallback</code> and <code>dbCallback</code> are called against the passed object if no errors are found.</p>

        
          <div class='highlight'><pre>    <span class="attribute">transmitDataToClients</span>: <span class="function"><span class="params">(err, localFile, obj, socketsCallback, dbCallback)</span> =&gt;</span>
        <span class="keyword">if</span> <span class="keyword">not</span> err?
            fs.readFile localFile, <span class="function"><span class="params">(err1, result)</span> =&gt;</span>
                <span class="keyword">if</span> err1?
                    sockets.sendServerError <span class="string">"Manager: could not read <span class="subst">#{localFile}</span>."</span>, err1
                <span class="keyword">else</span>
                    <span class="keyword">if</span> settings.general.debug
                        expresser.logger.info <span class="string">"Manager.transmitDataToClients"</span>, localFile</pre></div>
        
      
        
        <p>Try parsing the data as JSON.</p>

        
          <div class='highlight'><pre>                    <span class="keyword">try</span>
                        obj.data = JSON.parse result
                    <span class="keyword">catch</span> err2
                        expresser.logger.error err2
                        <span class="keyword">return</span>

                    socketsCallback obj</pre></div>
        
      
        
        <p>Verify and increase the refresh count.</p>

        
          <div class='highlight'><pre>                    counter = obj.refreshCount
                    <span class="keyword">if</span> <span class="keyword">not</span> counter? <span class="keyword">or</span> counter &lt; <span class="number">1</span>
                        counter = <span class="number">1</span>
                    <span class="keyword">else</span>
                        counter++
                    obj.refreshCount = counter</pre></div>
        
      
        
        <p>Save the updated data to the database.</p>

        
          <div class='highlight'><pre>                    obj.data = database.cleanObjectForInsertion obj.data
                    dbCallback obj, {<span class="attribute">patch</span>: <span class="literal">true</span>}
        <span class="keyword">else</span>
            expresser.logger.error <span class="string">"Manager.transmitDataToClients"</span>, localFile, err</pre></div>
        
      
        
        <h2 id="singleton-implementation">Singleton implementation</h2>

        
      
        
        
        
          <div class='highlight'><pre>Manager.<span class="function"><span class="title">getInstance</span> = -&gt;</span>
    <span class="property">@instance</span> = <span class="keyword">new</span> Manager() <span class="keyword">if</span> <span class="keyword">not</span> <span class="property">@instance</span>?
    <span class="keyword">return</span> <span class="property">@instance</span>

module.<span class="built_in">exports</span> = <span class="built_in">exports</span> = Manager.getInstance()</pre></div>
        
      
      <div class="fleur">h</div>
    </div>
  </div>
</body>
</html>
